package gcode.helloworld.java.socket.linecaller;

import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;

import org.apache.log4j.Logger;

public class SocketListener extends Thread {
	private Logger log	 = null;
	private ServerSocket server	= null;
	private BlockingQueue<Socket> queue   = null;
	private boolean running	= false;
	private int port 	= 0;
	private Thread workThread;
	public SocketListener(BlockingQueue<Socket> queue,int port){
		super();
		log = Logger.getLogger(getClass());
		this.queue = queue;
		this.port = port;
	}
	public void listen() throws IOException,BindException {
		log.info("listen ");
        server = new ServerSocket(port);
        start();
	}
	public void run(){
		log.info("run ");
		if(server==null){
			log.error("serverSocket is not start");
			return ;
		}
		workThread=Thread.currentThread();
		running=true;
		try{
	        while(running){
				try {
			        Socket s = server.accept();
			        log.info("accept "+s.getInetAddress()+":"+s.getPort());
			        queue.put(s);
				} catch (IOException e) {
					log.error("server.accept ",e);
				} catch (InterruptedException e) {
					log.error("queue.put interrupted!",e);
				}
	        }
		}finally{
			running	= false;
			close();
		}
	}
	private void close() {
		log.info("close ");
		if(server!=null
				&&!server.isClosed()){
			try {
				server.close();
			} catch (IOException e) {
				log.error("server.close ",e);
			}
		}
	}
	public void shutdown() throws InterruptedException{
		log.info("shutdown ");
		if(this.running){
			this.running=false;
			workThread.interrupt();
			if(workThread!=Thread.currentThread()){
				Thread.yield();
				Thread.sleep(500);
			}
		}
	}
}
